# -*- coding: utf-8 -*-
"""
 * @file common.py
 * @author SDK_TEAM
 * @brief
 * @version 0.1
 * @date 2022-11-3
 * Copyright:
 * © 2018 北京灵汐科技有限公司 版权所有。
 * 注意：以下内容均为北京灵汐科技有限公司原创，未经本公司允许，不得转载，否则将视为侵权；对于不遵守此声明或者其他违法使用以下内容者，本公司依法保留追究权。
 * © 2018 Lynxi Technologies Co., Ltd. All rights reserved.
 * NOTICE: All information contained here is, and remains the property of Lynxi. This file can not
 * be copied or distributed without the permission of Lynxi Technologies Co., Ltd.
"""
import json
import numpy as np
import pylynchipsdk as sdk
import ctypes
from . import common
from ctypes import *

BOXNUM = 128

pythonapi.PyCapsule_GetPointer.restype = c_void_p
pythonapi.PyCapsule_GetPointer.argtypes = [py_object, c_char_p]

class bbox(ctypes.Structure):
    _fields_ = [
        ("xmin", ctypes.c_uint32),
        ("ymin", ctypes.c_uint32),
        ("xmax", ctypes.c_uint32),
        ("ymax", ctypes.c_uint32),
        ("score", ctypes.c_float),
        ("id", ctypes.c_int),
        ("label", ctypes.c_char * 64),
    ]


class Box(ctypes.Structure):
    _fields_ = [("boxesnum", ctypes.c_uint16), ("boxes", ctypes.ARRAY(bbox, BOXNUM))]


class LabelInfo(ctypes.Structure):
    _fields_ = [("name", ctypes.c_char * 64)]


class LabelList(ctypes.Structure):
    _fields_ = [("labels", ctypes.c_void_p), ("labelNum", ctypes.c_int)]


class YoloxPostProcessInfo_t(ctypes.Structure):
    _fields_ = [
        ("height", ctypes.c_int),
        ("width", ctypes.c_int),
        ("ori_height", ctypes.c_int),
        ("ori_width", ctypes.c_int),
        ("score_threshold", ctypes.c_float),
        ("nms_threshold", ctypes.c_float),
        ("nms_top_k", ctypes.c_int),
        ("is_pad_resize", ctypes.c_int),
        ("output_tensor", ctypes.c_void_p),
        ("class_num", ctypes.c_int),
        ("labelList", LabelList),
        ("boxesInfo", ctypes.c_void_p),
        ("anchorSize", ctypes.c_int),
    ]

class LynSegBox(ctypes.Structure):
    _fields_ = [
        ("xmin", ctypes.c_uint32),
        ("ymin", ctypes.c_uint32),
        ("width", ctypes.c_uint32),
        ("height", ctypes.c_uint32),
        ("score", ctypes.c_float),
        ("id", ctypes.c_int),
        ("label", ctypes.c_char * 64),
        ("maskCol", ctypes.c_uint32),
        ("maskRow", ctypes.c_uint32)
    ]

class LynSegBoxesInfo(ctypes.Structure):
    _fields_ = [
        ("boxesNum", ctypes.c_uint16),
        ("boxes", LynSegBox * BOXNUM),
        ("maskData", ctypes.POINTER(ctypes.c_uint8)),
        ("maskDataLen", ctypes.c_uint32)
    ]

class SegmentPostProcessInfo_t(ctypes.Structure):
    _fields_ = [
        ("img_width", ctypes.c_int),
        ("img_height", ctypes.c_int),
        ("model_width", ctypes.c_int),
        ("model_height", ctypes.c_int),
        ("padx", ctypes.c_int),
        ("pady", ctypes.c_int),
        ("fatio", ctypes.c_double),
        ("output_tensor", ctypes.c_void_p),
        ("boxesInfo", ctypes.c_void_p),
    ]

class LynPosePoint(ctypes.Structure):
    _fields_ = [
        ("kps", ctypes.c_float * (17 * 3))
    ]

class LynPoseInfo(ctypes.Structure):
    _fields_ = [
        ("boxesNum", ctypes.c_uint16),
        ("points", LynPosePoint *BOXNUM),
        ("boxes", bbox * BOXNUM)
    ]

class PosePostProcessInfo_t(ctypes.Structure):
    _fields_ = [
        ("img_width", ctypes.c_int),
        ("img_height", ctypes.c_int),
        ("model_width", ctypes.c_int),
        ("model_height", ctypes.c_int),
        ("padx", ctypes.c_int),
        ("pady", ctypes.c_int),
        ("ratio", ctypes.c_double),
        ("output_tensor", ctypes.c_void_p),
        ("poseInfo", ctypes.c_void_p),
    ]

class YowoPostInfo_t(ctypes.Structure):
    _fields_ = [
        ("img_width", ctypes.c_int),
        ("img_height", ctypes.c_int),
        ("conf_threshold", ctypes.c_float),
        ("nms_threshold", ctypes.c_float),
        ("vis_threshold", ctypes.c_float),
        ("model_input_h", ctypes.c_int),
        ("model_input_w", ctypes.c_int),
        ("model_output_len", ctypes.c_int),
        ("boxesInfo", ctypes.c_void_p),
        ("output_tensor", ctypes.c_void_p),
    ]

class OSD_PARAM_T(ctypes.Structure):
    _fields_ = [
        ("imgData", ctypes.c_void_p),
        ("imgW", ctypes.c_int),
        ("imgH", ctypes.c_int),
        ("targetData", ctypes.c_void_p),
        ("targetNum", ctypes.c_int),
        ("deviceBoxInfo", ctypes.POINTER(Box)),
        ("apuBuffers", ctypes.c_void_p)
    ]

def create_label_list_with_names(label_file):
    with open(label_file) as f:
        names = json.loads(f.read())

    num_labels = len(names)

    label_info_array = (LabelInfo * num_labels)()

    for i, name in enumerate(names):
        label_info_array[i].name = name["desc"].encode("utf-8")

    label_info_dev, ret = sdk.lyn_malloc(ctypes.sizeof(LabelInfo) * num_labels)
    common.error_check(ret)

    label_info_array_np = np.frombuffer(
        label_info_array,
        dtype=np.uint8,
        count=ctypes.sizeof(LabelInfo) * num_labels // np.dtype(np.uint8).itemsize,
    )

    label_info_array_ptr = sdk.lyn_numpy_to_ptr(label_info_array_np)

    common.error_check(
        sdk.lyn_memcpy(
            label_info_dev,
            label_info_array_ptr,
            ctypes.sizeof(LabelInfo) * num_labels,
            sdk.lyn_memcpy_dir_t.ClientToServer,
        )
    )

    label_info_dev_ptr = pythonapi.PyCapsule_GetPointer(label_info_dev, None)

    label_list = LabelList()
    label_list.labels = label_info_dev_ptr
    # label_list.labels = ctypes.cast(label_info_array, ctypes.POINTER(LabelInfo))
    label_list.labelNum = num_labels

    return label_list, label_info_dev